/**
 * 1.如果函数内部有修改外部变量，则必然实现了Fn,FnMut,但不会实现Fn
 * 2.关键字move不影响实现的具体特质类型
 * 3.如果捕获变量，但是不修改，无论是否有使用move关键字，则都实现了FnOnce,FnMut,Fn
 */
#[allow(non_snake_case)]
fn test_FnOnce<T: FnOnce()>(f: T) {
    println!("调用FnOnce，只能一次");
    f();
}

#[allow(non_snake_case)]
fn test_FnMut<T: FnMut()>(mut f: T) {
    println!("调用FnMut，多次执行");
    f();
    f();
}
#[allow(non_snake_case)]
fn test_Fn<T: Fn()>(f: T) {
    println!("调用Fn，多次执行");
    f();
    f();
}
/**
 * 通过调用外部方法验证某个匿名函数到底实现了什么Fn特质
 */
fn main() {
    let name:String="rust".to_string();
    let mut name_mut:String="rust".to_string();

    //1.0 一个匿名函数，如果捕获外部变量，但是并不对变量做修改，则实现了FnOnce, FnMut和Fn特质
    let fx1_no_move_no_mut=||println!("{}",name);
    test_FnOnce(fx1_no_move_no_mut);
    test_FnMut(fx1_no_move_no_mut);
    test_Fn(fx1_no_move_no_mut);
    println!("{}",name);


    // 2~3的测试表明
    // a.如果内部修改了变量，但是不使用move，那么实现了FnOnce,FnMut特质(但不会实现Fn特质).变量归还
    // b.如果内部没有修改变量，但是使用了move，那么实现了FnOnce, FnMut和Fn特质，变量不归还

    //2.0 一个匿名函数，捕获外部变量，但是对变量做了修改，则实现了FnOnce, FnMut特质(但不会实现Fn特质)
    let mut fx2_no_move_mut=||{
        name_mut.push_str("!fx2_no_move_mut");
        println!("{}",name_mut);
    };
    //test_FnOnce(fx2_no_move_mut);
    test_FnMut(fx2_no_move_mut);
    println!("归还后：{}",name_mut);

    //3.0 一个匿名函数，如果捕获外部变量，但是并不对变量做修改，则实现了FnOnce, FnMut和Fn特质
    //但因为使用move,所以是不归还
    let fx3_move_no_mut= move ||println!("{}",name);
    //test_FnOnce(fx3_move_no_mut);
    //test_FnMut(fx3_move_no_mut);
    test_Fn(fx3_move_no_mut);
    //println!("{}",name);


    //4.0 实现FnOnce,FnMut.不归还
    let fx4_move_mut= move ||{
        name_mut.push_str("!fx4_move_mut");
        println!("{}",name_mut);
    };
    //test_FnOnce(fx4_move_mut);
    //test_FnMut(fx4_move_mut);
    //println!("第二次归还后：{}",name_mut); //已经move了不会归还
}